#include <stdint.h>
#include <stdio.h>

#include "appdefs.h"
#include "platform_config.h"
#include "stm32f10x.h"
#include "hw_config.h"
#include "lib_dbg.h"
#include "sht21.h"
#include "usb_lib.h"
#include "usb_endp.h"
#include "stm32_sdio_sd.h"


static void prvSetupUSART();
static void SHT21_Config();

/*
 * Serial Number  0x62 0x00 0x81 0x31 0x3E 0xE7 0x81 0x01 - через I2C (не верно)
 * Serial Number  0x00 0x80 0x01 0x1C 0x7E 0x08 0x01 0x33 - через прямое дерганье выводами (верно)
 */

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

__IO uint8_t PrevXferComplete = 1;
volatile uint32_t SysTickClock = 0;
extern volatile HID_STATE HIDState;

uint8_t volatile TransmiteTimeout = FALSE;

__IO uint8_t Send_Buffer[5]; // TODO Размер передающего буфера

uint8_t SHT21_SerialNumber[8];
uint8_t SHT21_UserRegister, SHT21_UserRegister2;
uint16_t sTMP, sHUM;


#define FLASH_START_BANK1	0x08010000
#define FLASH_START_BANK2	0x08090000
#define FLASH_SIZE	((512-64+7)*1024)

#define BLOCK_SIZE            512 /* Block Size in Bytes */
#define NUMBER_OF_BLOCKS      4  /* For Multi Blocks operation (Read/Write) */
#define MULTI_BUFFER_SIZE    (BLOCK_SIZE * NUMBER_OF_BLOCKS)

#define SD_OPERATION_ERASE          0
#define SD_OPERATION_BLOCK          1
#define SD_OPERATION_MULTI_BLOCK    2
#define SD_OPERATION_END            3

uint8_t Buffer_Block_Tx[BLOCK_SIZE]  __attribute__ ((aligned (8)));
uint8_t Buffer_Block_Rx[BLOCK_SIZE]  __attribute__ ((aligned (8)));

uint8_t Buffer_MultiBlock_Tx[MULTI_BUFFER_SIZE]  __attribute__ ((aligned (8)));
uint8_t Buffer_MultiBlock_Rx[MULTI_BUFFER_SIZE]  __attribute__ ((aligned (8)));

volatile TestStatus EraseStatus = FAILED, TransferStatus1 = FAILED, TransferStatus2 = FAILED;
__IO uint32_t SDCardOperation = SD_OPERATION_ERASE;


SD_Error SD_Return = SD_OK;
SD_CardInfo CardInfo;

//--------------------------------------------------------------------------
int main()
{
#ifdef DEBUG
	debug();
#endif
#ifdef BOOT_FROM_BANK2
	NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x08080000 );
#else
	NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x08000000 );
#endif

	SystemStartup();
	RCC_Configuration();
	GPIO_Configuration();
	SysTick_Config( SystemCoreClock / 1000 );
	prvSetupUSART();
	NVIC_Configuration();

#ifdef BOOT_FROM_BANK2
	FLASH_Unlock();
	FLASH_EraseOptionBytes();
	FLASH_BootConfig( FLASH_BOOT_Bank1 );
#endif

	printf( "H\n" );
	printf( "Application starting\n" );

	SHT21_Init();
	SHT21_SoftReset();
	SHT21_Config();



//	LED_GREEN_ON();
	
	SD_Return = SD_Init();

	if( SD_Return != SD_OK )
	{
		LED_RED_ON();
		SD_DeInit();
	}

	SD_Return = SD_GetCardInfo( &CardInfo );
	if( SD_Return != SD_OK )
	{
		LED_RED_ON();
		SD_DeInit();
	}

	SD_Return = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, CardInfo.CardCapacity-FLASH_SIZE, BLOCK_SIZE, NUMBER_OF_BLOCKS);
	SD_Return = SD_WaitReadOperation();
	while(SD_GetStatus() != SD_TRANSFER_OK);

	USB_Interrupts_Config();
	USB_Init();

	for(;;)
	{
		if( HIDState == HID_TEMPHUM )
		{
			if( SHT21_MeasureHM( TEMP, &sTMP ) )
			{
				printf("Error MeasureHM\n");
				LED_RED_ON();
			}
		}
//		temp = 175.72f*sRH/65536.0f - 46.85f;
//		humidity = 125.0f*sRH/65536.0f-6.0f;

		if( HIDState == HID_TEMPHUM )
		{
			if( SHT21_MeasureHM( HUMIDITY, &sHUM ) )
			{
				printf("Error MeasureHM\n");
				LED_RED_ON();
			}
		}
		GPIO_WriteBit( LED_GPIO_PORT, LED_GPIO_GREEN_PIN, (BitAction)(1 - GPIO_ReadOutputDataBit( LED_GPIO_PORT, LED_GPIO_GREEN_PIN ) ) );

		if( PrevXferComplete && (HIDState == HID_SENDDATA) && (TransmiteTimeout == TRUE) )
		{
			mat_auto();
			TransmiteTimeout = FALSE;
			TIM_Cmd( TIM6, ENABLE );
		}

		if( PrevXferComplete && (HIDState == HID_TEMPHUM) )
		{
			Send_Buffer[0] = 0x03;
			Send_Buffer[1] = sTMP >> 8;
			Send_Buffer[2] = sTMP & 0xFF;
			Send_Buffer[3] = sHUM >> 8;
			Send_Buffer[4] = sHUM & 0xFF;

			USB_SIL_Write( EP1_IN, (uint8_t *)Send_Buffer, 5 );
			SetEPTxValid( ENDP1 );
			PrevXferComplete = 0;
		}

	}
	return 0;
}


static void SHT21_Config()
{
uint32_t oldTick;

	oldTick = SysTickClock;
	while( ( SysTickClock - oldTick ) < 20 ) // Delay 15 ms
	{}

	if( SHT21_GetSerialNumber( SHT21_SerialNumber ) )
	{
		printf( "Error GetSerialNumber\n" );
		LED_RED_ON();
	}

	if( SHT21_ReadUserRegister( &SHT21_UserRegister ) )
	{
		printf( "Error ReadUserRegister1\n" );
		LED_RED_ON();
	}

	SHT21_UserRegister = (SHT21_UserRegister & ~SHT2x_RES_MASK) | SHT2x_RES_10_13BIT;
	SHT21_WriteUserRegister( &SHT21_UserRegister );

	if( SHT21_ReadUserRegister( &SHT21_UserRegister2 ) )
	{
		printf( "Error ReadUserRegister2\n" );
		LED_RED_ON();
	}
}

static void prvSetupUSART()
{
USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_Init( USART3, &USART_InitStructure );
	USART_Cmd( USART3, ENABLE );
}

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
  USART_SendData(USART3, (uint8_t) ch);

  /* Loop until the end of transmission */
  while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
  {}

  return ch;
}

